# -*- coding: utf-8 -*-

"""
@author: Laowang
@contact: QQ:1125564921
@Created on: 2022/6/21
@Remark: 
"""

from typing import List
from collections import defaultdict

from .ftx_api_cfg import FtxPlatConfig
from .ftx_utils import public_request_
from .ftx_client import FtxClient
from framework_strategy.gopy.gateways.settings import FTXAPISETTING
from framework_strategy.gopy.base import GateWay
from framework_strategy.gopy.base.constant import *
# from binance_api_cfg import auth_require, public_request, sign_encrypt_data
# from framework_strategy.gopy.gateways.utils import RequestParamterObj
from framework_strategy.gopy.gateways.utils import RequestParamterObj, public_request, \
    ResponseKlineObj, ResponseTickerObj, ResponseOrderBookObj, ResponseTradesObj,\
    ResponseOrderObj, ResponseCancelOrderObj, ResponseBalanceObj, ResponseAccountOrderObj

client = FtxClient(FTXAPISETTING.PUBLIC_KEY, FTXAPISETTING.SECRET_KEY)


# ################################################ #
# def server_time_response(data, parameter=None):
#     """ server time response """
#     print("[server_time_response] ", data)
#     ndata = dict()
#     ndata["data"] = data.get('serverTime')
#     return ndata


def market_config_response(data, parameter=None):
    """ account response """
    ndata = dict()
    for d in data:
        ndata[d.get('name')] = {
            "minMoney": None,
            "quotePrecision": len(str(int(1 / float(d.get('priceIncrement'))))) - 1,
            "quoteAssetPrecision": len(str(int(1 / float(d.get('sizeIncrement'))))) - 1,
        }
    return ndata


def kline_response(data, parameter=None):
    """ kline response """
    ndata = defaultdict(list)
    for d in data:
        ndata["data"].append(
            ResponseKlineObj(
                d['startTime'],
                d['open'],
                d['high'],
                d['low'],
                d['close'],
                d['volume'],
            )
        )
    return ndata


def ticker_response(data, parameter=None):
    """ tickers response """
    if not data:
        return data
    ndata = ResponseTickerObj(
        data.get('bid'),
        None,
        data.get('ask'),
        None,
        None)
    return {"data": ndata}


def tickers_response(data, parameter=None):
    """ tickers response """
    if not data:
        return data
    ndata = dict()
    for d in data:
        ndata[d.get('name')] = ResponseTickerObj(
            d.get('bid'),
            None,
            d.get('ask'),
            None,
            None)
    return {"data": ndata}


def depth_response(data, parameter=None):
    """ depth response """
    if not data:
        return data
    ndata = dict()
    ndata["data"] = ResponseOrderBookObj(data["asks"], data["bids"])
    return ndata


def trades_response(data, parameter=None):
    """ trades response """
    if not data:
        return data
    ndata = defaultdict(list)
    for d in data:
        ndata["data"].append(ResponseTradesObj(
            d.get('id'),
            d.get('data')[0].get('lastPrice'),
            d.get('data')[0].get('quotation'),
            d.get('data')[0].get('side'),
            d.get('ts')
        ))
    return ndata


def balance_response(data, parameter=None):
    """ balance response """
    if not data:
        return data
    ndata = defaultdict(list)
    for d in data:
        ndata["data"].append(
            ResponseBalanceObj(
                d.get('coin'),
                d.get('free'),
                d.get('total')-d.get('free'),
            )
        )
    return ndata


def send_order_response(data, parameter=None):
    """ order response """
    if not data:
        return data
    ndata = dict()
    ndata["data"] = ResponseOrderObj(data.get('result').get('id'))
    return ndata


def cancel_order_response(data, parameter=None):
    """ cancel order response """
    if not data:
        return data
    res = ResponseCancelOrderObj(
        None,
        data.get('success')
    )
    return {"data": res}


def get_order_response(data, parameter=None):
    """ get order response """
    if not data:
        return data
    data = data["data"]
    res = ResponseAccountOrderObj(
        data.get('result').get('size'),
        data.get('result').get('price'),
        data.get('result').get('id'),
        data.get('result').get('status'),
        data.get('result').get('side'),
        data.get('result').get('type'),
    )
    return {"data": res}


def open_order_response(data, parameter=None):
    """ open order response """
    ndata = defaultdict(list)
    if not data:
        return {"data": ndata["data"]}
    for d in data["data"]:
        ndata["data"].append(
            ResponseAccountOrderObj(
                data.get('result').get('size'),
                data.get('result').get('price'),
                data.get('result').get('id'),
                data.get('result').get('status'),
                data.get('result').get('side'),
                data.get('result').get('type'))
        )
    return ndata


# ################################################ #
@public_request(key=public_request_, response_handle=market_config_response)
def get_all_market_config(self, event):
    """ Access all market config """
    print("--get_all_market_config--", self, event)
    res = client.get_markets()
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=kline_response)
def get_klines(self, event):
    """ Get Klines """
    print(event.event_data.kwargs)
    res = client.get_historical_prices(**event.event_data.kwargs)
    print("--get_klines--", res, event)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=ticker_response)
def get_ticker(self, event):
    """ All aggregate market """
    print("--get_tickers--", self, event)
    res = client.get_single_market(**event.event_data.kwargs) 
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=tickers_response)
def get_tickers(self, event):
    """ All aggregate market """
    print("--get_tickers--", self, event)
    res = client.get_markets(**event.event_data.kwargs) 
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=depth_response)
def get_depth(self, event):
    """ Gain market depth """
    print("--get_depth--", self, event)
    res = client.get_orderbook(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=trades_response)
def get_trades(self, event):
    """ Get trade history """
    print("--get_trades--", self, event)
    # res = client.historical_trades(**event.event_data.kwargs)
    res = client.get_trades(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=balance_response)
def get_balance(self, event):
    """ Get account info """
    print("--get_account--", self, event)
    res = client.get_balances()
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=send_order_response)
def send_order(self, event):
    """ Order """
    print("--send_order--", self, event)
    res = client.place_order(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=cancel_order_response)
def cancel_order(self, event):
    """ Cancel order """
    print("--cancel_order--", self, event)
    res = client.cancel_order(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=get_order_response)
def get_order(self, event):
    """ Get order """
    print("--get_order--", self, event)
    res = client.get_order(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


@public_request(key=public_request_, response_handle=open_order_response)
def get_open_order(self, event):
    """ Obtain outstanding orders """
    print("--get_open_order--", self, event)
    res = client.get_open_orders(**event.event_data.kwargs)
    res = RequestParamterObj(res, '', event)
    return res


# @public_request(key=public_request_, response_handle=server_time_response)
# def get_server_time(self, event):
#     """ Get server time now """
#     res = client.time()
#     res = RequestParamterObj(res, '', event)
#     print("--get_server_time--", self, event, res)
#     return res
# # @auth_require
# def send_orders(self, event):
#     """ Orders """
#     print("--send_orders--", self, event)
#     return True
# # @auth_require
# def cancel_orders(self, event):
#     """ Cancel orders """
#     print("--cancel_orders--", self, event)
#     return True
# # @auth_require
# def get_orders(self, event):
#     """ Obtain all orders information"""
#     print("--get_orders--", self, event)
#     return True
# # @auth_require
# def get_balance(self, event):
#     """ Get account balance """
#     print("--get_balance--", self, event)
#     res = client.account(event)
#     return res
# # @auth_require
# def get_fund(self, event):
#     """ Gets the corresponding information for an account """
#     print("--get_fund--", self, event)
#     res = client.account(event)
#     return res
# # @public_request
# def get_ticker(self, event):
#     """ Aggregate market """
#     print("--get_ticker--", self, event)
#     res = client.ticker_price(event)
#     return res


class FTXGateway(GateWay):
    exchanges = ["FTX"]
    def __init__(self, main_engine, event_engine, gateway_name="FTX", proxy=None) -> None:
        super().__init__(main_engine, event_engine, gateway_name, proxy)

    ON_EVENT: List = [
        # (FTX_EVENT_SERVERTIMES, get_server_time),
        # (FTX_EVENT_ACCOUNT, get_balance),
        (FTX_EVENT_MARKETCONFIG, get_all_market_config),
        (FTX_EVENT_KLINE, get_klines),
        (FTX_EVENT_TICKER, get_ticker),
        (FTX_EVENT_TICKERS, get_tickers),
        (FTX_EVENT_MARKETDEPTH, get_depth),
        (FTX_EVENT_ORDER_TRADE, get_trades),
        (FTX_EVENT_ACCOUNT_BALANCE, get_balance),
        # (FTX_EVENT_ACCOUNT_FUND, get_fund),
        (FTX_EVENT_SENDORDER, send_order),
        # (FTX_EVENT_SENDORDERS, send_orders),
        (FTX_EVENT_CANCELORDER, cancel_order),
        # (FTX_EVENT_CANCELORDERS, cancel_orders),
        (FTX_EVENT_ORDER_STATUS, get_order),
        (FTX_EVENT_OPENORDER, get_open_order),
        # (FTX_EVENT_ORDERS_STATUS, get_orders),
    ]
